package com.china08.yxyapi.api.manage.tec.teaching.weikecheng.upload;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.china08.yxyapi.api.YxyApiBaseController;
import com.china08.yxyapi.entity.db.res.YxyResTemp;
import com.china08.yxyapi.entity.db.res.YxyResVideoBlock;
import com.china08.yxyapi.model.YxyApiReqModel;
import com.china08.yxyapi.model.YxyApiRespModel;
import com.china08.yxyapi.repository.db.YxyResTempRepository;
import com.china08.yxyapi.repository.db.YxyResVideoBlockRepository;
import com.china08.yxyapi.util.YxyResUtil;

/**
 * 合并文件
 * 
 * @author Json
 *
 */
@CrossOrigin
@RestController
public class WeikechengBlockMergeController extends YxyApiBaseController {

    private static final Logger LOGGER = LoggerFactory.getLogger(WeikechengBlockMergeController.class);

    @Autowired
    private YxyResVideoBlockRepository yxyResVideoBlockRepository;

    @Value("${weike.storage.upload.video}")
    private String uploadBasePath;

    @Autowired
    private YxyResTempRepository yxyResTempRepository;

    @RequestMapping(value = "/api_yw/manage/tec/teaching/weikecheng/block/merge", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public RespModel process(@RequestBody ReqModel model) {
        RespModel respModel = new RespModel();

        boolean flag = joinFile(model.md5, model.extension);
        // 合并正常
        if (flag) {
            try {
                String location = YxyResUtil.getPath() + File.separator + model.md5.substring(0, 2) + File.separator
                        + model.md5 + "." + model.extension;
                // 查看md5合并文件后的md5值
                String md5 = DigestUtils.md5Hex(new FileInputStream(uploadBasePath + location));
                // 合成的文件没有问题
                // 删除临时文件
                // 数据库删除临时文件
                if (model.md5.equals(md5)) {
                    YxyResTemp temp = yxyResTempRepository.findByMd5(md5);
                    if (temp == null) {
                        temp = new YxyResTemp();
                        temp.setMd5(md5);
                        temp.setLocation(location);
                        yxyResTempRepository.save(temp);
                    }
                    respModel.status = 1;
                    respModel.location = location;
                } else {
                    LOGGER.error("md5值不同");
                    // 删除错误的文件 和文件记录
                    respModel.status = 4;
                    respModel.location = "md5值不同:前台:" + model.md5 + "====后台md5" + md5;
                }
                List<YxyResVideoBlock> list = yxyResVideoBlockRepository.findByMd5(model.md5);
                for (YxyResVideoBlock yxyResVideoBlock : list) {
                    yxyResVideoBlockRepository.delete(yxyResVideoBlock);
                }
                FileUtils.deleteDirectory(
                        new File(uploadBasePath + "/temp" + YxyResUtil.getPathMonth() + File.separator + md5));
            } catch (Exception e) {
                LOGGER.error("获取文件的md5值异常:" + e);
                respModel.status = 5;
                respModel.location = "获取文件的md5值异常:" + e;
                e.printStackTrace();
            }
        } else {
            LOGGER.error("文件合并异常,请查看");
            respModel.status = 3;
            respModel.location = "文件合并异常";
        }
        // 所有的视频片段
        return respModel;
    }

    protected static class RespModel extends YxyApiRespModel {
        public Integer status = 0;
        public String location;
    }

    protected static class ReqModel extends YxyApiReqModel {

        public String md5;// 整个文件的md5
        public String extension; // 文件后缀

        public void check() {
            Assert.notNull(StringUtils.defaultIfBlank(md5, null), "视频md5不能为空");
            Assert.notNull(StringUtils.defaultIfBlank(extension, null), "视频后缀不能为空");
        }
    }

    private boolean joinFile(String md5, String extension) {

        boolean flag = true;
        long start = System.currentTimeMillis();
        try {
            LOGGER.info("开始拼接视频文件");
            // 视频存储路径
            String fileDirectory = uploadBasePath + YxyResUtil.getPath() + File.separator + md5.substring(0, 2);
            File sf = new File(fileDirectory);
            FileUtils.forceMkdir(sf);

            String filePath = sf.getPath() + File.separator + md5 + "." + extension;

            String fileTempPath = uploadBasePath + "/temp" + YxyResUtil.getPathMonth() + File.separator + md5;
            File file = new File(fileTempPath);
            if (file.isDirectory()) {
                String[] filelist = file.list();
                File file2 = null;
                OutputStream writer = new FileOutputStream(filePath);
                int len;
                byte[] cbuf = new byte[1024 * 2 * 1024];
                for (int i = 0; i < filelist.length; i++) {
                    file2 = new File(fileTempPath + File.separator + i);
                    if (!file2.exists()) {
                        LOGGER.info("片段不存在,片段为" + i);
                        flag = false;
                        writer.close();
                        return flag;
                    }
                    InputStream reader = new FileInputStream(file2);
                    while ((len = reader.read(cbuf, 0, cbuf.length)) != -1) {
                        writer.write(cbuf, 0, len);
                        writer.flush();
                    }
                    reader.close();
                }
                writer.close();
            } else {
                flag = false;
            }
        } catch (Exception e) {
            flag = false;
            LOGGER.error("合并片段异常", e);
        }
        LOGGER.info("合并片段用时:" + ((System.currentTimeMillis() - start) / 1000) + "s");
        return flag;

    }

}